Bitset in rust


러슀트둜 game of life κ΅¬ν˜„ν•˜κΈ°λ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ enum 벑터λ₯Ό μ΅œμ ν™” ν•  수 μžˆλŠ” λ°©λ²•μœΌλ‘œ μ–΄μ°¨ν”Ό bool 벑터인 μ…ˆμ΄λ―€λ‘œ λΉ„νŠΈμ…‹μ„ μ‚¬μš©ν•˜λŠ” 방법이 μ’‹κ² λ‹€κ³  νŒλ‹¨ν•˜μ—¬ κ΅¬ν˜„μ„ μ‹œμž‘ν•˜μ˜€λ‹€.

C++μ—μ„œ λΉ„νŠΈμ…‹μ„ λ§Œλ“€μ—ˆλ˜ 기얡이 μžˆμœΌλ―€λ‘œ λ”± 두 κ°€μ§€λ§Œ κΈ°μ–΅ν•˜λ©΄ λœλ‹€.

두 νŒŒλΌλ©”ν„°λ₯Ό κ΅¬ν•˜λŠ” ν•¨μˆ˜ bin_no 와 inner_idx λ₯Ό μž‘μ„±ν•˜μ˜€λ‹€. 이거 근데 λŸ¬μŠ€νŠΈμ—μ„œ 인라인 μ •μ˜ λͺ»ν•˜λ‚˜? => κ°„μ ‘μ μœΌλ‘œ μ™ΈλΆ€μ—μ„œ ν˜ΈμΆœλ˜μ§€ μ•ŠλŠ” private ν•¨μˆ˜μ— λŒ€ν•΄μ„  ꡳ이 인라인 ν•  ν•„μš” μ—†λ‹€.

use std::mem::size_of;

fn bin_no(idx: usize) -> usize {
	idx / <usize>() * 8
}

fn inner_idx(idx: usize) -> usize {
	idx % <usize>() * 8
}

Bitset νƒ€μž…κ³Ό μƒμ„±μžλ₯Ό μ •μ˜ν•΄λ³΄μž. μš°λ¦¬κ°€ λ§Œλ“€ λΉ„νŠΈμ…‹μ€ 초기 크기가 κ³ μ •λ˜μ–΄μžˆλ‹€. 아직은 λ°°μ—΄ 크기λ₯Ό μ œλ„€λ¦­ν•˜κ²Œ λ§Œλ“œλŠ” 방법을 λͺ¨λ₯΄λ‹ˆ 벑터λ₯Ό μ“°μž. generic array in rust

pub struct Bitset {
	bits: Vec<usize>,
}

impl Bitset {
	/// creates [false; size] like bitset
	pub fn with_size(size: usize) -> Self {
		let size = bin_no(size) + 1; // ν˜Ήμ‹œ λͺ¨λ₯΄λ‹ˆ μ—¬μœ λ‘­κ²Œ
		let mut v = Vec::with_capacity(size); // size μ•„λ‹™λ‹ˆλ‹€, capacity μž…λ‹ˆλ‹€.
		v.resize(size, 0);
		Bitset {bits: v}
	}

	/// indices의 각 μ›μ†Œλ“€μ˜ μΈλ±μŠ€κ°€ true인 μƒˆ Bitsetλ₯Ό λ°˜ν™˜ν•œλ‹€.
	pub fn from_indices(indices: &[usize]) -> Self {
		let size = bin_no(indices.len()) + 1;
		let mut v = Vec::with_capacity(size);
		v.resize(size, 0);	
		for i in indices.iter().cloned() {
			*v.get_mut(bin_no(i)).expect("Index out of bounds") |= 1 << inner_idx(i);
		}
		Bitset { bits: v }
	}
}

λ‹€μŒμ€ 인덱싱을 ν™œμš©ν•˜μ—¬ get, set을 ν•˜λŠ” λ©”μ„œλ“œλ₯Ό μ •μ˜ν•΄λ³΄μž

impl Bitset {
	pub fn get(&self, idx: usize) -> bool {
		self.bits.get(bin_no(idx))
			.expect("Index Out of Bounds") >> inner_idx(idx) & 0b01 == 1
	}
    pub fn set(&mut self, idx: usize) {
        *self.bits.get_mut(bin_no(idx))
	        .expect("Index Out of Bounds") |= 1 << inner_idx(idx);
    }
    pub fn reset(&mut self, idx: usize) {
        *self.bits.get_mut(bin_no(idx))
	        .expect("Index Out of Bounds") &= !(1 << inner_idx(idx));
    }
    pub fn set_to(&mut self, idx: usize, to: bool) {
        if to {
            self.set(idx);
        } else {
            self.reset(idx);
        }
    }

μ•„λž˜λŠ” λΉ„νŠΈμ…‹ κ΄€λ ¨ ν…ŒμŠ€νŠΈμ΄λ‹€. 러슀트둜 game of life κ΅¬ν˜„ν•˜κΈ° ν• λ•Œ 디버깅 용으둜 κ°„λ‹¨ν•˜κ²Œ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν–ˆλ‹€. μ΄λ•Œ 러슀트 λͺ¨λ“ˆ ꡬ쑰에 λŒ€ν•œ 이해λ₯Ό 덀으둜 μ–»μ–΄κ°”λ‹€.

  1. μœ λ‹› ν…ŒμŠ€νŠΈλŠ” ν…ŒμŠ€νŠΈ ν•˜λ €λŠ” λͺ¨λ“ˆκ³Ό 같은 파일 μ•ˆμ—μ„œ μˆ˜ν–‰ν•œλ‹€.
  2. ν…ŒμŠ€νŠΈ λͺ¨λ“ˆνŒŒμΌ μ•ˆμ— #[cfg(test)] mod tests{} λΈ”λŸ­ μ•ˆμ—μ„œ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ λœλ‹€. -- μžμ‹ λͺ¨λ“ˆμ€ λΆ€λͺ¨ λͺ¨λ“ˆμ˜ private μš”μ†Œλ“€μ„ 자유둭게 μ ‘κ·Όν•  수 μžˆλ‹€λŠ” 점 κΈ°μ–΅ν•˜κ³ .
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bin_no() {
        for i in 0..=128 {
            assert_eq!(i / 32, bin_no(i), "i : {}", i);
        }
    }

    #[test]
    fn test_init() {
        let bs = Bitset::with_size(32);
        assert_eq!(2, bs.bits.len());
        for i in 0..32 {
            assert_eq!(false, bs.get(i), "in index {i}");
        }
        let bs = Bitset::with_size(128);
        assert_eq!(5, bs.bits.len());
        for i in 0..128 {
            assert_eq!(false, bs.get(i), "in index {}", i);
        }
    }

    #[test]
    fn test_set_get() {
        let size = 128;
        let mut bs = Bitset::with_size(size);
        for i in 0..size {
            bs.set(i);
            assert!(bs.get(i));
        }
        for i in (0..size).rev() {
            bs.reset(i);
            assert!(!bs.get(i));
        }
    }
}


fixedbitset crateλ₯Ό μ‚¬μš©ν•˜λŠ” 방법도 μžˆλ‹€. ν•˜μ§€λ§Œ ꡳ이?